package net.lucamasini.ricette.client.ingredienti;

import java.util.*;

import net.lucamasini.ricette.client.RicettarioRequestFactory;
import net.lucamasini.ricette.client.ServiceBus;
import net.lucamasini.ricette.client.tipoingredienti.TipoIngredienteProxy;
import net.lucamasini.ricette.client.util.DigitFilter;

import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.requestfactory.client.RequestFactoryEditorDriver;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.*;

public class IngredientiDialog extends SimplePanel implements Editor<IngredienteProxy>{

	private final static RicettarioRequestFactory requestFactory = GWT.create(RicettarioRequestFactory.class);

	private static IngredientiDialogUiBinder uiBinder = GWT
			.create(IngredientiDialogUiBinder.class);

	interface IngredientiDialogUiBinder extends
			UiBinder<Widget, IngredientiDialog> {
	}

	@UiField
	DialogBox dialog;
	
	@UiField TextBox descrizione;
	@UiField IntegerBox calorie;
	@UiField CheckBox glutine;
	@UiField ListBox tipoIngrediente;
		
	@UiField Button ok;
	@UiField Button annulla;

	private Map<String, Integer> fromTipoIngredienteToIndex = new HashMap<String, Integer>();
	private Map<Integer, String> fromIndexToTipoIngrediente = new HashMap<Integer, String>();

	private final Ingredienti ingredienti;

	private IngredienteProxy ingrediente;
	
	interface IngredientiDriver extends RequestFactoryEditorDriver<IngredienteProxy, IngredientiDialog> {}
	
	private IngredientiDriver driver = GWT.create(IngredientiDriver.class);
	
	public IngredientiDialog(Ingredienti ingredienti) {
		add(uiBinder.createAndBindUi(this));
		
		requestFactory.initialize(ServiceBus.getEventbus());
		
		DigitFilter.applyTo(calorie);
		
		List<TipoIngredienteProxy> result = new ArrayList<TipoIngredienteProxy>(ingredienti.cachedTipoIngrediente.values());
		
		for(int i=0;i<result.size();i++) {
			TipoIngredienteProxy ti = result.get(i);
			tipoIngrediente.addItem(ti.getDescrizione(), ti.getId());
			fromTipoIngredienteToIndex.put(ti.getId(), i);
			fromIndexToTipoIngrediente.put(i, ti.getId());
		}

		this.ingredienti = ingredienti;
	}
	
	@UiHandler("ok")
	void onOk(ClickEvent event) {
		ok.setEnabled(false);

		final IngredientiRequest context = ingrediente();

		if (driver.hasErrors()) {
			Window.alert(driver.getErrors().toString());
		
			ok.setEnabled(true);

			return;
	    }

		context.salvaIngrediente(ingrediente, tipoIngrediente()).fire(new Receiver<Void>() {

			@Override
			public void onSuccess(Void response) {
				ingredienti.refreshIngredienti();
				dialog.hide();
			}
		});
	}

	private String tipoIngrediente() {
		return fromIndexToTipoIngrediente.get(tipoIngrediente.getSelectedIndex());
	}
	
	private IngredientiRequest ingrediente() {
		
		IngredientiRequest context = (IngredientiRequest) driver.flush();
		
		return context;
	}

	@UiHandler("annulla")
	void onCancella(ClickEvent event) {
		dialog.hide();
	}

	private void setIngrediente(IngredienteProxy ingrediente, RequestContext context) {
		
		this.ingrediente = ingrediente;

		driver.initialize(this);
	    driver.edit(ingrediente, context);
	}

	public void creaIngrediente() {
		RequestContext context = requestFactory.ingredientiRequest();
		modificaIngrediente(context.create(IngredienteProxy.class), context);
	}

	public void modificaIngrediente(IngredienteProxy i) {
		modificaIngrediente(i, requestFactory.ingredientiRequest());
	}

	public void modificaIngrediente(IngredienteProxy i, RequestContext context) {
		setIngrediente(i, context);

		ok.setEnabled(true);
		
		dialog.center();
		dialog.show();
	}
}
